#include "stdafx.h"
#include "CSensorEvents.h"
#include "CSensorManagerEvents.h"
#include <Sensorsapi.h>
#include <sensors.h>
#include <SensAPI.h>
#include <initguid.h>
#include <propkeydef.h>
#include <comutil.h>

#define DEBUG 1

CSensorManagerEvents::CSensorManagerEvents()
{
//	printf(__FUNCTION__);
	m_lRefCount = 1; //ref count initialized to 1
	m_pSensorEvents = new CSensorEvents(this);
}

CSensorManagerEvents::~CSensorManagerEvents(void)
{//    	printf(__FUNCTION__);
	if (NULL != m_pSensorEvents)
    {
        delete m_pSensorEvents;
        m_pSensorEvents = NULL;
    }
}

STDMETHODIMP CSensorManagerEvents::QueryInterface(REFIID riid, void** ppObject)
{//	printf(__FUNCTION__);
	HRESULT hr = S_OK;

	*ppObject = NULL;
	if (riid == __uuidof(ISensorManagerEvents))
	{
		*ppObject = reinterpret_cast<ISensorManagerEvents*>(this);
	}
	else if (riid == IID_IUnknown)
	{
		*ppObject = reinterpret_cast<IUnknown*>(this);
	}
	else
	{
		hr = E_NOINTERFACE;
	}

	if (SUCCEEDED(hr))
	{
		(reinterpret_cast<IUnknown*>(*ppObject))->AddRef();
	}

	return hr;
}

ULONG _stdcall CSensorManagerEvents::AddRef()
{//	printf(__FUNCTION__);
	m_lRefCount++;
	return m_lRefCount; 
}

ULONG _stdcall CSensorManagerEvents::Release()
{//	printf(__FUNCTION__);
	ULONG lRet = --m_lRefCount;

	if (m_lRefCount == 0)
	{
		delete this;
	}

	return lRet;
}

HRESULT CSensorManagerEvents::Initialize()
{
	HRESULT hr;

#if DEBUG
	printf("Initialize() ok\n");
#endif

	hr = m_spISensorManager.CoCreateInstance(CLSID_SensorManager);
	if (SUCCEEDED(hr))
	{
#if DEBUG
		printf("CoCreateInstance() ok\n");
#endif
		hr = m_spISensorManager->SetEventSink(this);
		if (SUCCEEDED(hr))
		{
			// Find all Sensors
			ISensorCollection *spSensors;
			hr = m_spISensorManager->GetSensorsByType(SENSOR_TYPE_COMPASS_3D, &spSensors);
			//m_spISensorManager->RequestPermissions(0,spSensors, TRUE);
			if (SUCCEEDED(hr) && NULL != spSensors)
			{
#if DEBUG
				printf("GetSensorsByCategory() ok\n");
#endif
				ULONG ulCount = 0;
				hr = spSensors->GetCount(&ulCount);
				printf("Sensors: %d\n", ulCount);
				if (SUCCEEDED(hr))
				{
					for(ULONG i=0; i < ulCount; i++)
					{
						ISensor *spSensor;
						hr = spSensors->GetAt(i, &spSensor);
						if (SUCCEEDED(hr))
						{
							hr = AddSensor(spSensor);
							if (SUCCEEDED(hr))
							{
								hr = m_pSensorEvents->GetSensorData(spSensor);
							}
						}
					}
				}
			}else{
				printf("No any sensors was found!\nReturn Code: 1\n");
				exit(1);
			}
		}
	}
	return hr;
}

HRESULT CSensorManagerEvents::Uninitialize()
{//	printf(__FUNCTION__);
	HRESULT hr = S_OK;
/*
	POSITION pos = m_Sensors.GetStartPosition();
	while (NULL != pos)
	{
		ISensor* pSensor = m_Sensors.GetNextValue(pos);
		RemoveSensor(pSensor);
	}
*/
	if (NULL != m_spISensorManager)
	{
		hr = m_spISensorManager->SetEventSink(NULL);
	}

	return hr;
}

HRESULT CSensorManagerEvents::OnSensorEnter(ISensor* pSensor, SensorState state)
{//	printf(__FUNCTION__);
	HRESULT hr = S_OK;

	if (NULL != pSensor)
	{
		SENSOR_TYPE_ID idType = GUID_NULL;
		hr = pSensor->GetType(&idType);
		if (SUCCEEDED(hr))
		{
			if (IsEqualIID(idType, SENSOR_TYPE_COMPASS_3D))
			{
				hr = AddSensor(pSensor);
				if (SUCCEEDED(hr))
				{
					if (SENSOR_STATE_READY == state)
					{
						//hr = m_pSensorEvents->GetSensorData(pSensor);
						printf("Ok\n");
					}
				}
			}
		}
	}
	else
	{
		hr = E_POINTER;
	}

	return hr;
}

HRESULT CSensorManagerEvents::AddSensor(ISensor* pSensor)
{//	printf(__FUNCTION__);
	HRESULT hr = S_OK;

	if (NULL != pSensor)
	{
		hr = pSensor->SetEventSink(m_pSensorEvents);
		if (SUCCEEDED(hr))
		{
			// Get the sensor's ID to be used as a key to store the sensor
			SENSOR_ID idSensor = GUID_NULL;
			hr = pSensor->GetID(&idSensor);
			if (SUCCEEDED(hr))
			{
				// Enter the sensor into the map and take the ownership of its lifetime
				pSensor->AddRef(); // the sensor is released in the destructor
				m_Sensors[idSensor] = pSensor;
			}
		}
	}
	else
	{
		hr = E_POINTER;
	}

	return hr;
}

HRESULT CSensorManagerEvents::RemoveSensor(ISensor* pSensor)
{//	printf(__FUNCTION__);
	HRESULT hr = S_OK;

	if (NULL != pSensor)
	{
		hr = pSensor->SetEventSink(m_pSensorEvents);
		if (SUCCEEDED(hr))
		{
			// Get the sensor's ID to be used as a key to store the sensor
			SENSOR_ID idSensor = GUID_NULL;
			hr = pSensor->GetID(&idSensor);
			if (SUCCEEDED(hr))
			{
				// Enter the sensor into the map and take the ownership of its lifetime
				pSensor->AddRef(); // the sensor is released in the destructor
				m_Sensors[idSensor] = pSensor;
			}
		}
	}
	else
	{
		hr = E_POINTER;
	}

	return hr;
}